#pragma once

#include <vector>
#include <functional>
#include <pthread.h>
#include "Socket.hpp"

namespace ns_tcp_server
{
    using func_t = std::function<void(int)>;

    class TcpServer;
    struct ThreadData
    {
        ThreadData(int fd, TcpServer *thisptr)
            : _serverfd(fd), _this(thisptr)
        {
        }
        int _serverfd;
        TcpServer *_this;
    };

    class TcpServer
    {
    private:
        static void *Routine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *td = (ThreadData *)args;
            Messagelog(NORMAL, "执行任务的thread[%p]和sockfd[%d]", pthread_self(), td->_serverfd);
            td->_this->Excute(td->_serverfd); // 执行任务
            close(td->_serverfd);
            delete td;
            return nullptr;
        }

    public:
        TcpServer(uint16_t port, const std::string &ip = "0.0.0.0")
        {
            _listensock = _sock_function.Socket();
            _sock_function.Bind(_listensock, port, ip);
            _sock_function.Listen(_listensock);
        }

        void start()
        {
            while (true)
            {
                std::string cli_ip;
                uint16_t cli_port;
                int serverfd = _sock_function.Accept(_listensock, &cli_ip, &cli_port);
                if (serverfd == -1)
                {
                    continue;
                }
                Messagelog(NORMAL, "accept a client ip:%s port:%d", cli_ip.c_str(), cli_port);
                ThreadData *td = new ThreadData(serverfd, this);
                pthread_t tid;
                pthread_create(&tid, nullptr, Routine, td);
            }
        }

        // 服务端绑定要执行的任务
        void BindServer(const func_t &func)
        {
            _tasks.push_back(func);
        }

    private:
        void Excute(int serverfd) // 执行
        {
            for (auto &fun : _tasks)
            {
                fun(serverfd);
            }
        }

    private:
        // TCP协议通信，服务端send只需要向文件描述符里写就可以,不需要cli_ip和cli_port
        // int _sock;
        // std::string _ip;
        // uint16_t _port;
        int _listensock;
        Sock _sock_function;
        std::vector<func_t> _tasks;
    };
}